iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 13
1

這張圖是 Hello world 執行後,歷經的過程。

Reference

User space v.s. Kernel space

這裡要先辨別,作業系統的 User space 與 Kernel space 的差異。Kernel space 可以操作任何的系統資源,包括存取任何位置的記憶體,相對的,User space 能存取的資源相對有限。這樣分開的目的也很簡單,避免當 User Space 故障的時候,整個系統連帶崩潰。舉例來說,在 User Space 執行程式,就好比你在使用的 Chrome 瀏覽器,當它遭受某種原因而無法執行,你總不希望你的 Youtube 正在播放音樂受到影響吧?因此,區別 User space 與 kernel space 可以有效的讓重要的程式不受使用者的影響。

首先,先找到昨天寫的 Helloworld 程式,準備執行它

用strace追蹤程式的系統呼叫 (Syscall)

接著在 terminal 中,下指令:

strace ./helloworld

得到結果如下:

execve("./helloworld", ["./helloworld"], 0x7ffea93b1be0 /* 35 vars */) = 0
brk(NULL)                               = 0x555598cec000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffd42478d60) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=78465, ...}) = 0
mmap(NULL, 78465, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fb5ede6e000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360r\2\0\0\0\0\0"..., 832) = 832
lseek(3, 64, SEEK_SET)                  = 64
read(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784) = 784
lseek(3, 848, SEEK_SET)                 = 848
read(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32) = 32
lseek(3, 880, SEEK_SET)                 = 880
read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\313\351\317\363\304;\227\2279\257\26\201\266\32=X"..., 68) = 68
fstat(3, {st_mode=S_IFREG|0755, st_size=2025032, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb5ede6c000
lseek(3, 64, SEEK_SET)                  = 64
read(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784) = 784
lseek(3, 848, SEEK_SET)                 = 848
read(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32) = 32
lseek(3, 880, SEEK_SET)                 = 880
read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\313\351\317\363\304;\227\2279\257\26\201\266\32=X"..., 68) = 68
mmap(NULL, 2032984, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb5edc7b000
mmap(0x7fb5edca0000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7fb5edca0000
mmap(0x7fb5ede18000, 303104, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19d000) = 0x7fb5ede18000
mmap(0x7fb5ede62000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e6000) = 0x7fb5ede62000
mmap(0x7fb5ede68000, 13656, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb5ede68000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7fb5ede6d540) = 0
mprotect(0x7fb5ede62000, 12288, PROT_READ) = 0
mprotect(0x5555984e6000, 4096, PROT_READ) = 0
mprotect(0x7fb5edeae000, 4096, PROT_READ) = 0
munmap(0x7fb5ede6e000, 78465)           = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
brk(NULL)                               = 0x555598cec000
brk(0x555598d0d000)                     = 0x555598d0d000
write(1, "Hello, world!\n", 14Hello, world!
)         = 14
exit_group(14)                          = ?
+++ exited with 14 +++

在 Hello world 被呼叫後,經過以上過程。因為 strace 從 fork() 後開始追,因此,第一個獲得的函式是execve(),後續步驟包含寫入、寫出資料、最後離開。

用lstrace追蹤函式庫函式

在 terminal 中,下指令:

ltrace ./helloworld

得到結果如下:

Hello, world!
+++ exited (status 14) +++

輸出無結果

結論

這兩天的文章是程式的ㄧ生與它執行後的結果。明天開始就會開始帶一些實戰,讓大家好好瞭解特定程式碼的長相!


上一篇
Day12 - Hello world 的誕生 - 實戰篇
下一篇
Day14 - 史上最強Debugger - 人體肉眼 Debugger
系列文
逆向工程 – 從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言